﻿using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Babylon.Toolbox
{
    public class ParticleEffect : Effect
    {
        private readonly EffectParameter _currentTimeParam;
        private readonly EffectParameter _sizeDataParam;
        private readonly EffectParameter _viewParam;
        private readonly EffectParameter _projParam;
        private readonly EffectParameter _durationParam;
        private readonly EffectParameter _endVelocityRatioParam;
        private readonly EffectParameter _environmentForcesParam;
        private readonly EffectParameter _minMaxRotationParam;
        private readonly EffectParameter _minTeintParam;
        private readonly EffectParameter _maxTeintParam;
        private readonly EffectParameter _alphaRatioParam;

        public ParticleEffect(GraphicsDevice device) : base(device, "Babylon.Toolbox", "Particles/Effect/ParticleEffect")
        {
            _currentTimeParam = GetParameter("CurrentTime");
            _sizeDataParam = GetParameter("SizeData");
            _viewParam = GetParameter("View");
            _projParam = GetParameter("Proj");
            _durationParam = GetParameter("Duration");
            _endVelocityRatioParam = GetParameter("EndVelocityRatio");
            _environmentForcesParam = GetParameter("EnvironmentForces");
            _minMaxRotationParam = GetParameter("MinMaxRotation");
            _minTeintParam = GetParameter("MinTeint");
            _maxTeintParam = GetParameter("MaxTeint");
            _alphaRatioParam = GetParameter("AlphaRatio");

            MinTeint = new Vector3(1, 1, 1);
            MaxTeint = new Vector3(1, 1, 1);
        }

        public override void Apply()
        {
            _currentTimeParam.SetValue(CurrentTime);
            _sizeDataParam.SetValue(new Vector4(MinStartSize, MaxStartSize, MinEndSize, MaxEndSize));
            _projParam.SetValue(Proj);
            _viewParam.SetValue(View);
            _durationParam.SetValue(new Vector2(ParticleDuration, DurationRandomness));
            _endVelocityRatioParam.SetValue(EndVelocityRatio);
            _environmentForcesParam.SetValue(EnvironmentForces);
            _minMaxRotationParam.SetValue(new Vector2(MinRotationSpeed, MaxRotationSpeed));
            _minTeintParam.SetValue(MinTeint);
            _maxTeintParam.SetValue(MaxTeint);
            _alphaRatioParam.SetValue(AlphaRatio);
            Device.Textures[0] = Texture;
            base.Apply();
        }

        /// <summary>
        /// Get or set the current global time (in seconds)
        /// </summary>
        public float CurrentTime { get; set; }

        /// <summary>
        /// Get or set Alpha ratio to apply to the output color
        /// </summary>
        public float AlphaRatio { get; set; }

        /// <summary>
        /// Get or set the minimum size of a particle at it's start
        /// </summary>
        public float MinStartSize { get; set; }
        
        /// <summary>
        /// Get or set the maximum size of a particle at it's start
        /// </summary>
        public float MaxStartSize { get; set; }


        /// <summary>
        /// Get or set the minimum size of a particle at it's end
        /// </summary>
        public float MinEndSize { get; set; }


        /// <summary>
        /// Get or set the maximum size of a particle at it's end
        /// </summary>
        public float MaxEndSize { get; set; }


        /// <summary>
        /// Get or set the View Matrix
        /// </summary>
        public Matrix View { get; set; }

        /// <summary>
        /// Get or set the projection matrix
        /// </summary>
        public Matrix Proj { get; set; }

        /// <summary>
        /// Get or set the particle avg duration (in seconds)
        /// </summary>
        public float ParticleDuration { get; set; }

        /// <summary>
        /// Get or set the velocity amount at the end of the life of a particle
        /// </summary>
        public float EndVelocityRatio { get; set; }

        /// <summary>
        /// Get or set environment forces to apply to the particles (influence the trajectory)
        /// </summary>
        public Vector3 EnvironmentForces { get; set; }

        /// <summary>
        /// get or set the Minimum rotation speed of a particle
        /// </summary>
        public float MinRotationSpeed { get; set; }

        /// <summary>
        /// Get or set the Maximum rotation speed of a particle
        /// </summary>
        public float MaxRotationSpeed { get; set; }

        /// <summary>
        /// Get or set the minimum teint to apply to the output color
        /// </summary>
        public Vector3 MinTeint { get; set; }

        /// <summary>
        /// Get or set the maximum teint to apply to the output color
        /// </summary>
        public Vector3 MaxTeint { get; set; }

        /// <summary>
        /// Get or set the quantity of randomness applied to particle life duration
        /// </summary>
        public float DurationRandomness { get; set; }

        /// <summary>
        /// Get or set the texture used for the particle color
        /// </summary>
        public Texture2D Texture { get; set; }
    }
}
